package com.example.server.signature;

import com.example.server.util.RsaUtils;
import com.example.common.vo.RespBean;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;

@Aspect
@Component
public class YebVerifyAdvice {
    @Pointcut("@annotation(com.example.server.signature.YebVerify)")
    public void yebVerify() {

    }

    /**
     * 0.去掉@RequestBody注解(不会去读取json)
     * 1.advice中获取sign
     * 2.advice中获取正文
     * 3.使用Rsa根据进行验签
     * 4.Json转换为指定格式的对象，该对象在advice手动的装配
     * 5.验签成功，再去执行后续的业务逻辑
     *
     * @param joinPoint
     * @throws Throwable
     */
//    @Before("yebVerify()")
    @Around("yebVerify()")
    public Object verifyAdvice(ProceedingJoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        String sign = request.getHeader("sign");

        Object[] args = joinPoint.getArgs();

        try {

            int contentLength = request.getContentLength();
            if (contentLength < 0) {
                throw new RuntimeException("没有数据需要验证");
            }
            byte[] buffer = new byte[contentLength];
            for (int i = 0; i < contentLength; ) {
                int readLength = request.getInputStream().read(buffer, i, contentLength - i);
                if (readLength == -1) {
                    break;
                }
                i += readLength;
            }
            String characterEncoding = request.getCharacterEncoding();
            if (StringUtils.isEmpty(characterEncoding)) {
                characterEncoding = StandardCharsets.UTF_8.toString();
            }
            // 生成数据原文
            String json = new String(buffer, characterEncoding);

//            String json = new ObjectMapper().writeValueAsString(args[0]);

            boolean verify = RsaUtils.verify(json, sign);
            if (!verify) {
                throw new RuntimeException("验证签名失败！");
            }

            Class<?> aClass = args[0].getClass();
            Object data = new ObjectMapper().readValue(json, aClass);

            args[0] = data;

            Object proceed = joinPoint.proceed(args);

            return proceed;

        } catch (Throwable e) {
            throw RespBean.SIGN_VERIFY_FAILED_ERROR_202.toException()
                    .addMessage(e.getMessage());
        }
    }
}
